/**
 * @addtogroup lmu
 * scc_lmu_instance
 * @brief        定位模块升级组件
 * @code{c}

    //1、本组件支持鸿泉定位模块的升级，为通用组件。
    //2、组件开始使用调用TSccLmuInstanceInit，结束使用调用TSccLmuInstanceDeinit
    //3、支持定位模块自适应识别，通过调用TSccLmuInstanceStart函数启动升级时设置模块类型参数。
    //4、目前只支持中科微模块的升级，后续会加入其它模块的升级功能。
    //5、模块默认升级波特率为9600，一般设备和模块通信只支持这个波特率，所以在实现时不用实现设置波特率的回调
    //6、9600波特率情况下，一般升级固件完成时间为6-7分钟左右，可以通过TSccLmuInstanceSetTimeout来升级最长时间，默认为600S。
    //7、升级进度和最后升级结果可以通过接口来获得。

    //回调事件实现
    // 获取定位模块的输出数据
    static Int32 ReadModule(void *sender, Byte *recv_buf, Int32 buf_size)
    {
        ...
    }

    // 往定位模块发送数据
    static Int32 WriteModule(void *sender, Byte *send_buf, Int32 buf_size)
    {
        ...
    }

    // 设置模块波特率
    static Bool SetModuleBaudrate(void *sender, Int32 baudrate)
    {
        ...
    }

    // 获得模块固件数据流
    static Int32 GetDataPosition(void *sender, Int32 pos, Byte *buf, Int32 buf_size)
    {
        ...
    }

    // 升级结果通知
    static void OnUpgradeResult(void *sender, Int32 result)
    {
        ...
    }

    // 设置回调函数
    Bool Init(TSccLmuInstance *scc_lmu_instance)
    {
        TSccLmuInstanceSetCallBack(scc_lmu_instance, NULL, GetDataPosition, kSccLmuFuncGetData);
        TSccLmuInstanceSetCallBack(scc_lmu_instance, NULL, ReadModule, kSccLmuFuncReadModule);
        TSccLmuInstanceSetCallBack(scc_lmu_instance, NULL, WriteModule, kSccLmuFuncWriteModule);
        TSccLmuInstanceSetCallBack(scc_lmu_instance, NULL, OnUpgradeResult, kSccLmuFuncUpgradeResult);
        return True;
    }

    // 使用升级组件示例
    TSccLmuInstance scc_lmu_intance;
    if (TSccLmuInstanceInit(&scc_lmu_intance))
    {
        Init(&scc_lmu_intance);

        file_lenth = GetFileSize(g_file_name_); ///< 获取升级文件大小
        TSccLmuInstanceStart(&scc_lmu_intance, g_module_type, file_lenth, SfGetTickCount()); ///< 开始升级
        TSccLmuInstanceSetLogFlag(&scc_lmu_intance, g_log_flag_); ///< 设置日志打印标志

        while (True)
        {
            TSccLmuInstanceRunOnce(&scc_lmu_intance, SfGetTickCount());

            if (TSccLmuInstanceGetUpgradeStatus(&scc_lmu_intance) == kSccLmuStatusFinish ||
                TSccLmuInstanceGetUpgradeStatus(&scc_lmu_intance) == kSccLmuStatusIdle)
            {
                // 升级完成，退出
                break;
            }
            SfSleep(10);
        }
        ...
    }
    TSccLmuInstanceDinit(&scc_lmu_intance);
 * @endcode
 * @{
 */
/**
 * @file         scc_lmu_instance.h
 * @brief        定位模块升级组件
 * @note
 * @author       dengdeshou
 * @date         2020-04-23
 * @version      1.0
 *
 * @par          修改日志
 * <table>
 * <tr><th>Date        <th>Version               <th>Author          <th>Description
 * <tr><td>2020-04-23   <td>1.0                   <td>Dengdeshou      <td>创建初始版本
 * @copyright    杭州鸿泉物联网技术股份有限公司
 */

#ifndef _SCC_LMU_INSTANCE_H_
#define _SCC_LMU_INSTANCE_H_

#include "ofc/ofc_types.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * 定位模块升级
 * @par 示例
 
 */

/**
 * 升级结果通知
 * @param sender: 对象指针
 * @param result: 升级结果，成功或者返回相关错误码
 * return
 */
typedef void(*TSccLmuDoUpgradeResult)(void *sender, Int32 result);

/**
 * 往定位模块发送数据
 * @param sender: 对象指针
 * @param send_buf: 发送缓冲区指针
 * @param buf_size: 发送缓冲区数据长度
 * return 实际发送的大小
 */
typedef Int32(*TSccLmuDoWrite)(void *sender, Byte *send_buf, Int32 buf_size);

/**
 * 获取定位模块的输出数据
 * @param sender: 对象指针
 * @param recv_buf: 接收缓冲区指针
 * @param buf_size: 接收缓冲区数据长度
 * @return 实际读取的大小
 */
typedef Int32(*TSccLmuDoRead)(void *sender, Byte *recv_buf, Int32 buf_size);

/**
 * 获得模块固件数据流
 * @param sender: 对象指针
 * @param pos: 读取数据流的起始地址
 * @param buf: 存放数据流的缓冲区
 * @param buf_size: 缓冲区长度
 * @return 实际读取的大小
 */
typedef Int32(*TSccLmuDoGetDataPosition)(void *sender, Int32 pos, Byte *buf, Int32 buf_size);

/**
 * 设置模块波特率
 * @note:默认9600，可以不设置这个回调
 * @param sender: 对象指针
 * @param baudrate: 波特率数值
 * @return 设置成功或失败
 */
typedef Bool(*TSccLmuSetBaudrate)(void *sender, Int32 baudrate);

/**
 * 升级进度通知
 * @param sender: 对象指针
 * @return 设置成功或失败
 */
typedef void(*TSccLmuProgress)(void *sender, Int32 percent);

/**
 * 回调函数类型定义
 */
enum TSccLmuCallBackEnumTag
{
    kSccLmuCallBackGetData = 0, ///< 读取数据流函数接口
    kSccLmuCallBackReadModule = 1, ///< 从模块读取数据
    kSccLmuCallBackWriteModule = 2, ///< 发送模块数据
    kSccLmuCallBackSetBaudrate = 3, ///< 设置波特率
    kSccLmuCallBackUpgradeResult = 4, ///< 升级结果通知    
    kSccLmuCallBackProgress = 5, ///< 升级进度通知
};
typedef enum TSccLmuCallBackEnumTag TSccLmuCallBackEnum;

/**
 * 升级状态定义
 */
enum TSccLmuUpgradeStatusEnumTag
{
    kSccLmuStatusIdle = 0x00, ///< 空闲状态
    kSccLmuStatusMatching = 0x01, ///< 匹配模块信息，自动识别模块
    kSccLmuStatusDoing = 0x02, ///< 正在升级中
    kSccLmuStatusFinish = 0x03, ///< 升级结束
};
typedef enum TSccLmuUpgradeStatusEnumTag TSccLmuUpgradeStatusEnum;

/**
 * 开始升级结果值
 */
enum TSccLmuStartResultEnumTag
{
    kSccLmuStartResultSucess = 0, ///< 成功
    kSccLmuStartResultAlready = 1, ///< 启动升级失败，模块已经在升级过程中
    kSccLmuStartResultUnkown = 2, ///< 启动升级失败，无法识别的模块类型
    kSccLmuStartResultObjectNotInit = 3, ///< 启动升级失败，对象未初始化
    kSccLmuStartResultFileLenth = 4, ///< 未传入文件长度
    kSccLmuStartResultOther = 5, ///< 启动升级失败，其他错误
};
typedef enum TSccLmuStartResultEnumTag TSccLmuStartResultEnum;

/**
 * 定位模块类型
 */
enum TSccLmuModuleTypeEnumTag
{
    kSccLmuModuleTypeAuto = 0, ///< 自适应模式
    kSccLmuModuleTypeAtgm = 1, ///< 中科微ATGM模块
    kSccLmuModuleTypeUblox = 2, ///< UBLOX模块
    kSccLmuModuleTypeMax = 3,
};
typedef enum TSccLmuModuleTypeEnumTag TSccLmuModuleTypeEnum;

typedef struct TSccLmuInstanceTag TSccLmuInstance;
struct TSccLmuInstanceTag
{
    char buf[752];
};

/**
 * 初始化函数
 * @param self: 对象指针
 * @return 成功或失败
 */
Bool TSccLmuInstanceInit(TSccLmuInstance *self);

/**
 * 去初始化函数
 * @param self: 对象指针
 * @return
 */
void TSccLmuInstanceDeinit(TSccLmuInstance *self);

/**
 * 开始模块升级
 * @param self: 对象指针
 * @param img_size: 模块固件的大小
 * @param module_type: 定位模块类型，参考TSccLmuModuleTypeEnum
 * @return 启动升级结果,参考TSccLmuStartResultEnum
 */
Byte TSccLmuInstanceStart(TSccLmuInstance *self, Byte module_type, DWord file_lenth, DWord ticks);

/**
 * 停止模块升级
 * @param self: 对象指针
 * @return 成功或失败
 */
Bool TSccLmuInstanceStop(TSccLmuInstance *self);

 /**
  * 升级状态机调用
  * @param self: 对象指针
  * @param ticks: 当前时间戳，单位：毫秒
  * @return
  */
void TSccLmuInstanceRunOnce(TSccLmuInstance *self, DWord ticks);

/**
 * 设置升级超时时间
 * @param self: 对象指针
 * @param time_out: 超时时间，单位为秒，默认为600
 * @return 成功或失败
 */
Bool TSccLmuInstanceSetTimeout(TSccLmuInstance *self, DWord timeout);

/**
 * 获取升级超时时间
 * @param self: 对象指针
 * @return 超时时间，单位秒，默认为600
 */
DWord TSccLmuInstanceTimeout(TSccLmuInstance *self);

/**
 * 获取升级错误码
 * @param self: 对象指针
 * @return 升级错误码，参考TSccLmuErrorCodeEnum
 */
Int8 TSccLmuInstanceGetErrorCode(TSccLmuInstance *self);

/**
 * 获取当前升级状态
 * @param self: 对象指针
 * @return 当前升级状态，参考TSccLmuUpgradeStatusEnum
 */
Byte TSccLmuInstanceGetUpgradeStatus(TSccLmuInstance *self);

/**
 * 设置日志打印标志
 * @param self: TSccLmuInstance对象指针
 * @param log_flag: 打印日志标志，0-不打印，1-打印
 * return
 */
void TSccLmuInstanceSetLogFlag(TSccLmuInstance *self, Byte log_flag);

/**
 * 获取日志打印标志
 * @param self: TSccLmuInstance对象指针
 * return 打印日志标志，0-不打印，1-打印
 */
Byte TSccLmuInstanceGetLogFlag(TSccLmuInstance *self);

/**
 * 设置回调函数
 * @param scc_lmu: TSccLmu对象指针
 * @param sender: 回调函数所在对象
 * @param func: 回调函数指针
 * @param func_type: 回调函数类型，参考TSccLmuCallBackEnum
 * return 
 */
void TSccLmuInstanceSetCallBack(TSccLmuInstance *self, void *sender, void *func, Byte func_type);

#ifdef __cplusplus
}
#endif
#endif
/**
 * @}
 */
